package com.gydz.gydzbaseframeworkboot.CsdE.controller;


import cn.hutool.db.sql.SqlUtil;
import com.gydz.gydzbaseframeworkboot.Common.utils.export.ExcelUtil;
import com.gydz.gydzbaseframeworkboot.Common.utils.page.PageParam;
import com.gydz.gydzbaseframeworkboot.Common.utils.page.PageUtils;
import com.gydz.gydzbaseframeworkboot.Common.utils.page.TableDataInfo;
import com.gydz.gydzbaseframeworkboot.Common.utils.result.ResultUtils;
import com.gydz.gydzbaseframeworkboot.Common.utils.sqlUtil.domain.TableSelect;
import com.gydz.gydzbaseframeworkboot.Common.utils.sqlUtil.service.SqlUtilsService;
import com.gydz.gydzbaseframeworkboot.CsdE.domain.EInterfaceCsd;
import com.gydz.gydzbaseframeworkboot.CsdE.domain.EInterfaceCsdCallRec;
import com.gydz.gydzbaseframeworkboot.CsdE.service.IEInterfaceCsdCallRecService;
import com.gydz.gydzbaseframeworkboot.SystemControl.utils.Log;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.*;

@RestController
@RequestMapping("/EInterfaceCsdCallRec")
public class EInterfaceCsdCallRecController {

    private static final Logger log = LoggerFactory.getLogger(EInterfaceCsdCallRecController.class);


    @Autowired
    private IEInterfaceCsdCallRecService eInterfaceCsdCallRecService;

    @Autowired
    private SqlUtilsService sqlUtilsService;


    @ResponseBody
    @Log(remark = "查询E接口呼叫记录")
    @RequestMapping("/list")
    public void list(HttpServletResponse httpServletResponse, @ModelAttribute("eInterfaceCsdCallRec") EInterfaceCsdCallRec eInterfaceCsdCallRec) throws IOException {

        TableSelect tableSelect = new TableSelect();
        tableSelect.setTableSchema("csd_e");
        tableSelect.setPrefix("e_csd_callrec_");
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
        if(eInterfaceCsdCallRec.getStartTime() == null){
            ResultUtils result =  ResultUtils.fail("查询E接口呼叫失败,请选择查询时间范围");
            ResultUtils.responseResult(httpServletResponse,result);
            return ;
        }else {
            tableSelect.setDateMin(dateFormat.format(eInterfaceCsdCallRec.getStartTime()));
        }
        if(eInterfaceCsdCallRec.getEndTime() == null){
            eInterfaceCsdCallRec.setEndTime(new Date());
        }
        tableSelect.setDateMax(dateFormat.format(eInterfaceCsdCallRec.getEndTime()));

        List<String> tableList = sqlUtilsService.selectTabeName(tableSelect);
        if(tableList.isEmpty()){
            ResultUtils result =  ResultUtils.fail("没有该时间范围的表");
            ResultUtils.responseResult(httpServletResponse,result);
            return ;
        }


        PageUtils.startPage(new PageParam(eInterfaceCsdCallRec.getiDisplayStart(),eInterfaceCsdCallRec.getiDisplayLength(),eInterfaceCsdCallRec.getsSortDir(),eInterfaceCsdCallRec.getsSortCol()));
        eInterfaceCsdCallRec.setTableNameList(tableList);
        List<EInterfaceCsdCallRec> list = eInterfaceCsdCallRecService.selectEInterfaceCsdCallrecList(eInterfaceCsdCallRec);
        list.forEach(this::convertEnums);
        TableDataInfo tableDataInfo = PageUtils.getDataTable(list);

        ResultUtils result =  ResultUtils.succ(200,"查询E接口呼叫记录成功",tableDataInfo);
        ResultUtils.responseResult(httpServletResponse,result);
    }


    @ResponseBody
    @Log(remark = "导出E接口呼叫记录")
    @RequestMapping("/exportData")
    public void exportData(HttpServletRequest request, @ModelAttribute("eInterfaceCsdCallRec") EInterfaceCsdCallRec eInterfaceCsdCallRec, HttpServletResponse httpServletResponse) throws IOException {
        TableSelect tableSelect = new TableSelect();
        tableSelect.setTableSchema("csd_e");
        tableSelect.setPrefix("e_csd_callrec_");
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
        if(eInterfaceCsdCallRec.getStartTime() == null){
            ResultUtils result =  ResultUtils.fail("查询E接口呼叫失败,请选择查询时间范围");
            ResultUtils.responseResult(httpServletResponse,result);
            return ;
        }else {
            tableSelect.setDateMin(dateFormat.format(eInterfaceCsdCallRec.getStartTime()));
        }
        if(eInterfaceCsdCallRec.getEndTime() == null){
            eInterfaceCsdCallRec.setEndTime(new Date());
        }
        tableSelect.setDateMax(dateFormat.format(eInterfaceCsdCallRec.getEndTime()));

        List<String> tableList = sqlUtilsService.selectTabeName(tableSelect);
        if(tableList.isEmpty()){
            ResultUtils result =  ResultUtils.fail("没有该时间范围的表");
            ResultUtils.responseResult(httpServletResponse,result);
            return ;
        }
        eInterfaceCsdCallRec.setsSortCol("");
        eInterfaceCsdCallRec.setTableNameList(tableList);
        List<EInterfaceCsdCallRec> list = eInterfaceCsdCallRecService.selectEInterfaceCsdCallrecList(eInterfaceCsdCallRec);
        //转换字段
        list.forEach(this::convertEnums);
        //导出excel
        // 导出excel
        String[] excelHeader = {
                "序号", "IMSI号码", "MSISDN号码", "ctcs id标识", "车次号", "呼叫开始时间", "结束时间", "被叫号码（RBC号码）",
                "呼叫速率类型", "呼叫开始lrbgid", "呼叫开始速度", "呼叫开始公里标", "呼叫开始小区", "呼叫开始Bts",
                "呼叫开始C3类型", "呼叫结束lrbgid", "呼叫结束速度", "呼叫结束公里标", "呼叫结束小区", "呼叫结束Bts",
                "呼叫结束C3类型", "公里标方向", "释放发起方",
                "pri拆链原因", "Cdr类型", "cdr结果", "特殊标签", "是否本局呼叫", "V110状态",
                "采集设备设备号", "采集设备端口号", "采集设备时隙号"
        };

        String[] ds_titles = {
                "dataNum", "imsi", "msIsdn", "ctcsId", "trainNum", "startTime", "endTime", "calledNum",
                "dataRate", "startLrbgId", "startSpeed", "startKilo", "startLacCi", "startBtsRef",
                "startC3Mode", "discLrbgId", "discSpeed", "discKilo", "discLacCi", "discBtsRef",
                "discC3Mode", "kiloDir", "discDir", "discCause", "cdrType", "cdrResult", "specialTag",
                "localCall", "v110Status", "devNum", "portNum", "slotNum"
        };

        int[] widths = {
                256 * 14, 256 * 14, 256 * 24, 256 * 14, 256 * 16, 256 * 24, 256 * 24, 256 * 14,
                256 * 14, 256 * 14, 256 * 14, 256 * 14, 256 * 14, 256 * 14, 256 * 14, 256 * 14,
                256 * 14, 256 * 14, 256 * 14, 256 * 14, 256 * 14, 256 * 24, 256 * 24, 256 * 24,
                256 * 14, 256 * 14, 256 * 14, 256 * 14, 256 * 14, 256 * 14, 256 * 14, 256 * 14,
        };

        int[] ds_format = {
                2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 // 修改: 添加最后一个元素以匹配 ds_titles 的长度
        };
        try {
            List<Map<String, Object>> data = new ArrayList<Map<String, Object>>();
            if (list != null && !list.isEmpty()) {
                SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                int index = 1;
                for (EInterfaceCsdCallRec rdata : list) {
                    Map<String, Object> map = new HashMap<String, Object>();
                    map.put("dataNum", index);
                    map.put("imsi", rdata.getImsi());
                    map.put("msIsdn", rdata.getMsIsdn());
                    map.put("ctcsId", rdata.getCtcsId());
                    map.put("trainNum", rdata.getTrainNum());
                    map.put("startTime", rdata.getStartTime() != null ? format.format(rdata.getStartTime()) : "");
                    map.put("endTime", rdata.getEndTime() != null ? format.format(rdata.getEndTime()) : "");
                    map.put("calledNum", rdata.getCalledNum());
                    map.put("dataRate", rdata.getDataRate());
                    map.put("startLrbgId", rdata.getStartLrbgId());
                    map.put("startSpeed", rdata.getStartSpeed());
                    map.put("startKilo", rdata.getStartKiloStr());
                    map.put("startLacCi", rdata.getStartLacCi());
                    map.put("startBtsRef", rdata.getStartBtsRef());
                    map.put("startC3Mode", rdata.getStartC3Mode());
                    map.put("discLrbgId", rdata.getDiscLrbgId());
                    map.put("discSpeed", rdata.getDiscSpeed());
                    map.put("discKilo", rdata.getDiscKiloStr());
                    map.put("discLacCi", rdata.getDiscLacCi());
                    map.put("discBtsRef", rdata.getDiscBtsRef());
                    map.put("discC3Mode", rdata.getDiscC3Mode());
                    map.put("kiloDir", rdata.getKiloDirStr());
                    map.put("discDir", rdata.getDiscDirStr());
                    map.put("discCause", rdata.getDiscCauseStr());
                    map.put("cdrType", rdata.getCdrType());
                    map.put("cdrResult", rdata.getCdrResult());
                    map.put("specialTag", rdata.getSpecialTag());
                    map.put("localCall", rdata.getLocalCall());
                    map.put("v110Status", rdata.getV110Status());
                    map.put("devNum", rdata.getDevNum());
                    map.put("portNum", rdata.getPortNum());
                    map.put("slotNum", rdata.getSlotNum());
                    index++;
                    data.add(map);
                }
            }
            SimpleDateFormat format = new SimpleDateFormat("yyyyyMMddHHmmss");
            ExcelUtil.export("E接口呼叫记录数据"+format.format(new Date()), "数据列表", excelHeader, ds_titles, ds_format, widths, data, request, httpServletResponse);
        } catch (Exception e) {
            log.error("导出数据异常", e);
        }

    };

    private void convertEnums(EInterfaceCsdCallRec eInterfaceCsdCallRec){
        if (eInterfaceCsdCallRec == null) return;

        eInterfaceCsdCallRec.setStartKiloStr(convertStartKiloStr(eInterfaceCsdCallRec.getStartKilo()));
        eInterfaceCsdCallRec.setDiscKiloStr(convertStartKiloStr(eInterfaceCsdCallRec.getDiscKilo()));
        eInterfaceCsdCallRec.setKiloDirStr(convertKiloDir(eInterfaceCsdCallRec.getKiloDir()));
        eInterfaceCsdCallRec.setDiscDirStr(convertdiscDir(eInterfaceCsdCallRec.getDiscDir()));
        eInterfaceCsdCallRec.setDiscCauseStr(convertdiscCause(eInterfaceCsdCallRec.getDiscCause()));

    }

    private String convertStartKiloStr(String kilo){
        if (StringUtils.isNotBlank(kilo) && kilo.length()>3){
            return   "K"+kilo.substring(0, kilo.length()-3)+"+"+kilo.substring(kilo.length()-3);
        }else {
            return kilo;
        }
    }

    private String convertKiloDir(Byte tmp) {
        if (tmp == null) return "";
        switch (tmp) {
            case 0: return "增加";
            case 3: return "减少";
            default: return "";
        }
    }
    public static final Map<Integer, String> Q931_CAUSE_CODE_VALS;
    static {
        Q931_CAUSE_CODE_VALS = new HashMap<>();
        Q931_CAUSE_CODE_VALS.put(0x00, "Call successful");
        Q931_CAUSE_CODE_VALS.put(0x01, "Unallocated (unassigned) number");
        Q931_CAUSE_CODE_VALS.put(0x02, "No route to specified transit network");
        Q931_CAUSE_CODE_VALS.put(0x03, "No route to destination");
        Q931_CAUSE_CODE_VALS.put(0x04, "Send special information tone");
        Q931_CAUSE_CODE_VALS.put(0x05, "Misdialled trunk prefix");
        Q931_CAUSE_CODE_VALS.put(0x06, "Channel unacceptable");
        Q931_CAUSE_CODE_VALS.put(0x07, "Call awarded and being delivered in an established channel");
        Q931_CAUSE_CODE_VALS.put(0x08, "Prefix 0 dialed but not allowed");
        Q931_CAUSE_CODE_VALS.put(0x09, "Prefix 1 dialed but not allowed");
        Q931_CAUSE_CODE_VALS.put(0x0A, "Prefix 1 dialed but not required");
        Q931_CAUSE_CODE_VALS.put(0x0B, "More digits received than allowed, call is proceeding");
        Q931_CAUSE_CODE_VALS.put(0x10, "Normal call clearing");
        Q931_CAUSE_CODE_VALS.put(0x11, "User busy");
        Q931_CAUSE_CODE_VALS.put(0x12, "No user responding");
        Q931_CAUSE_CODE_VALS.put(0x13, "No answer from user (user alerted)");
        Q931_CAUSE_CODE_VALS.put(0x14, "Subscriber absent");
        Q931_CAUSE_CODE_VALS.put(0x15, "Call rejected");
        Q931_CAUSE_CODE_VALS.put(0x16, "Number changed");
        Q931_CAUSE_CODE_VALS.put(0x17, "Reverse charging rejected");
        Q931_CAUSE_CODE_VALS.put(0x18, "Call suspended");
        Q931_CAUSE_CODE_VALS.put(0x19, "Call resumed");
        Q931_CAUSE_CODE_VALS.put(0x1A, "Non-selected user clearing");
        Q931_CAUSE_CODE_VALS.put(0x1B, "Destination out of order");
        Q931_CAUSE_CODE_VALS.put(0x1C, "Invalid number format (incomplete number)");
        Q931_CAUSE_CODE_VALS.put(0x1D, "Facility rejected");
        Q931_CAUSE_CODE_VALS.put(0x1E, "Response to STATUS ENQUIRY");
        Q931_CAUSE_CODE_VALS.put(0x1F, "Normal unspecified");
        Q931_CAUSE_CODE_VALS.put(0x21, "Circuit out of order");
        Q931_CAUSE_CODE_VALS.put(0x22, "No circuit/channel available");
        Q931_CAUSE_CODE_VALS.put(0x23, "Destination unattainable");
        Q931_CAUSE_CODE_VALS.put(0x25, "Degraded service");
        Q931_CAUSE_CODE_VALS.put(0x26, "Network out of order");
        Q931_CAUSE_CODE_VALS.put(0x27, "Transit delay range cannot be achieved");
        Q931_CAUSE_CODE_VALS.put(0x28, "Throughput range cannot be achieved");
        Q931_CAUSE_CODE_VALS.put(0x29, "Temporary failure");
        Q931_CAUSE_CODE_VALS.put(0x2A, "Switching equipment congestion");
        Q931_CAUSE_CODE_VALS.put(0x2B, "Access information discarded");
        Q931_CAUSE_CODE_VALS.put(0x2C, "Requested circuit/channel not available");
        Q931_CAUSE_CODE_VALS.put(0x2D, "Pre-empted");
        Q931_CAUSE_CODE_VALS.put(0x2E, "Precedence call blocked");
        Q931_CAUSE_CODE_VALS.put(0x2F, "Resources unavailable, unspecified");
        Q931_CAUSE_CODE_VALS.put(0x31, "Quality of service unavailable");
        Q931_CAUSE_CODE_VALS.put(0x32, "Requested facility not subscribed");
        Q931_CAUSE_CODE_VALS.put(0x33, "Reverse charging not allowed");
        Q931_CAUSE_CODE_VALS.put(0x34, "Outgoing calls barred");
        Q931_CAUSE_CODE_VALS.put(0x35, "Outgoing calls barred within CUG");
        Q931_CAUSE_CODE_VALS.put(0x36, "Incoming calls barred");
        Q931_CAUSE_CODE_VALS.put(0x37, "Incoming calls barred within CUG");
        Q931_CAUSE_CODE_VALS.put(0x38, "Call waiting not subscribed");
        Q931_CAUSE_CODE_VALS.put(0x39, "Bearer capability not authorized");
        Q931_CAUSE_CODE_VALS.put(0x3A, "Bearer capability not presently available");
        Q931_CAUSE_CODE_VALS.put(0x3E, "Inconsistency in designated outgoing access information and subscriber class");
        Q931_CAUSE_CODE_VALS.put(0x3F, "Service or option not available, unspecified");
        Q931_CAUSE_CODE_VALS.put(0x41, "Bearer capability not implemented");
        Q931_CAUSE_CODE_VALS.put(0x42, "Channel type not implemented");
        Q931_CAUSE_CODE_VALS.put(0x43, "Transit network selection not implemented");
        Q931_CAUSE_CODE_VALS.put(0x44, "Message not implemented");
        Q931_CAUSE_CODE_VALS.put(0x45, "Requested facility not implemented");
        Q931_CAUSE_CODE_VALS.put(0x46, "Only restricted digital information bearer capability is available");
        Q931_CAUSE_CODE_VALS.put(0x4F, "Service or option not implemented, unspecified");
        Q931_CAUSE_CODE_VALS.put(0x51, "Invalid call reference value");
        Q931_CAUSE_CODE_VALS.put(0x52, "Identified channel does not exist");
        Q931_CAUSE_CODE_VALS.put(0x53, "Call identity does not exist for suspended call");
        Q931_CAUSE_CODE_VALS.put(0x54, "Call identity in use");
        Q931_CAUSE_CODE_VALS.put(0x55, "No call suspended");
        Q931_CAUSE_CODE_VALS.put(0x56, "Call having the requested call identity has been cleared");
        Q931_CAUSE_CODE_VALS.put(0x57, "Called user not member of CUG");
        Q931_CAUSE_CODE_VALS.put(0x58, "Incompatible destination");
        Q931_CAUSE_CODE_VALS.put(0x59, "Non-existent abbreviated address entry");
        Q931_CAUSE_CODE_VALS.put(0x5A, "Destination address missing, and direct call not subscribed");
        Q931_CAUSE_CODE_VALS.put(0x5B, "Invalid transit network selection (national use)");
        Q931_CAUSE_CODE_VALS.put(0x5C, "Invalid facility parameter");
        Q931_CAUSE_CODE_VALS.put(0x5D, "Mandatory information element is missing");
        Q931_CAUSE_CODE_VALS.put(0x5F, "Invalid message, unspecified");
        Q931_CAUSE_CODE_VALS.put(0x60, "Mandatory information element is missing");
        Q931_CAUSE_CODE_VALS.put(0x61, "Message type non-existent or not implemented");
        Q931_CAUSE_CODE_VALS.put(0x62, "Message not compatible with call state or message type non-existent or not implemented");
        Q931_CAUSE_CODE_VALS.put(0x63, "Information element non-existent or not implemented");
        Q931_CAUSE_CODE_VALS.put(0x64, "Invalid information element contents");
        Q931_CAUSE_CODE_VALS.put(0x65, "Message not compatible with call state");
        Q931_CAUSE_CODE_VALS.put(0x66, "Recovery on timer expiry");
        Q931_CAUSE_CODE_VALS.put(0x67, "Parameter non-existent or not implemented - passed on");
        Q931_CAUSE_CODE_VALS.put(0x6E, "Message with unrecognized parameter discarded");
        Q931_CAUSE_CODE_VALS.put(0x6F, "Protocol error, unspecified");
        Q931_CAUSE_CODE_VALS.put(0x7F, "Internetworking, unspecified");
        Q931_CAUSE_CODE_VALS.put(0xFF, "Non-specific failure");
    }

    private String convertdiscDir(Byte tmp) {
        if (tmp == null) return "";
        switch (tmp) {
            case 2: return "MSC";
            case 3: return "RBC";
            default: return "";
        }
    }

    private String convertdiscCause(Integer tmp){
        return Q931_CAUSE_CODE_VALS.get(tmp);
    }





}
